質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

Path.GetFileNameが使えません。

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 359

takumi0610

score 42

前提・実現したいこと

コードファーストで、ファイルをアップロードし、最終的にDBに保存したいです。
こちらの質問では、まず表題のエラーを解決したいと思っております。

※以前、DBファーストでファイルのアップロード、データベースへの保存は、以下の記事を参考に、実装できました。
ファイルのアップロードを行うには?
ASP.NET MVCでアップロードしたファイルをデータベースに登録するには?

今回は、以下のサイトを参考に、ファイルアップロード方法を学んでいるところですが、その過程で表題のエラーが発生しました。
MVC でファイルのアップロード

発生している問題・エラーメッセージ

コントローラーファイルの
「Dim filename As String = path.GetFileName(postedFile.FileName)」
の箇所で、以下のエラーが発生しております。
添付画像も参照お願いします。

ローカル変数 'path' は宣言されているため、参照できません。

該当のソースコード

※UploadModels.vb(モデルファイル)

Public Class UploadModels

    Public Property CustomId As String

    Public Property PostedFile As HttpPostedFileBase

End Class

※Upload.vbhtml(ビューファイル)

@modelType UploadToDB.UploadModels

@Code
    ViewData("Title") = "Upload"
End Code

<script type="text/javascript">
    //<![CDATA[
    $(function () {
        $('#ajaxUpload').on('click', function (e) {
            // FormData オブジェクトの利用
            var fd = new FormData(document.querySelector("form"));

            // 追加データを以下のようにして送信できる。フォーム
            // データの一番最後に追加されて送信される
            fd.append("CustomField", "This is some extra data");

            $.ajax({
                url: '/home/upload',
                method: 'post',
                data: fd,
                processData: false, // jQuery にデータを処理させない
                contentType: false  // contentType を設定させない
            }).done(function (response) {
                $("#result").empty;
                $("#result").text(response);
            }).fail(function (jqXHR, textStatus, errorThrown) {
                $("#result").empty;
                $("#result").text('textStatus: ' + textStatus +
                    ', errorThrown: ' + errorThrown);
            });
        });
    });
    //]]>
</script>

<h2>Upload</h2>

<div>
    @Using (Html.BeginForm("Upload", "Home", FormMethod.Post, New With {.enctype = "multipart/form-data"}))
        'form 内の隠しフィールドは Ajax でも送信される。
        'なので以下に設定したトークンは送信される。
        'もちろんクッキーのトークンも送信されるので、アクションメソッドに [ValidateAntiForgeryToken] を付与すればCSRF の検証はできる
        @Html.AntiForgeryToken()

        'name 属性はモデルのクラスのプロパティ名と同じにしないとサーバー側でモデルバインディングされないので注意。
        '大文字小文字は区別しない。

        @<input type="file" name="postedfile" size="50" />
        @<button type="submit">送信</button>

        @ViewBag.Result

    End Using

    <div>
        <input type="button" id="ajaxUpload" value="Ajax Upload" />
    </div>

</div>

※HomeController.vb(コントローラファイル)

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports System.Web.Mvc
Imports System.ComponentModel.DataAnnotations
Imports UploadToDB.UploadModels
Imports System.IO

Namespace UploadToDB.Controller

    Public Class HomeController
        Inherits System.Web.Mvc.Controller

        Function Index() As ActionResult
            Return View()
        End Function

        Function About() As ActionResult
            ViewData("Message") = "Your application description page."

            Return View()
        End Function

        Function Contact() As ActionResult
            ViewData("Message") = "Your contact page."

            Return View()
        End Function

        Public Function Upload() As ActionResult
            Return View()
        End Function


        <HttpPost()>
        <ValidateAntiForgeryToken()>
        Public Function Upload(ByVal model As UploadModels) As ActionResult
            Dim result As String = ""
            Dim postedFile As HttpPostedFileBase = model.PostedFile

            If postedFile IsNot Nothing AndAlso postedFile.ContentLength > 0 Then
                Dim filename As String = path.GetFileName(postedFile.FileName)
                Dim path As String = Server.MapPath("~/UploadedFiles") & "\" & filename
                postedFile.SaveAs(path)
                result = filename & " (" & postedFile.ContentType & ") - " + postedFile.ContentLength.ToString() & " bytes アップロード完了"
            Else
                result = "ファイルアップロードに失敗しました"
            End If

            If Request.IsAjaxRequest() Then
                Return Content(result)
            Else
                ViewBag.Result = result
                Return View()
            End If
        End Function
    End Class

End Namespace

※MyMvcContext.vb()コンテキストファイル)

Imports System.Data.Entity
Imports UploadToDB

Public Class MyMvcContext : Inherits DbContext
    Public Property Photo As DbSet(Of UploadModels) ' Photoテーブル
End Class

試したこと

エラー箇所を確認したところ、本来、参考サイトでは、「Path.GetFileName」となっている箇所が、「path.GetFileName」と
「p」が小文字になっていたので、入力ミスかと思い、修正しましたが、
修正箇所からカーソルが外れると、自動的に「path」に戻りました。

エラー文を調べたところ、「変数が宣言される前に使用されている際のエラー」とのことだったので、
「直後に、pathを宣言しているのに、直前にpathを使っているから表示されているエラー」だと思い、
そもそもなぜ、「Path」が「path」に変わるのかを考えました。

「Path.GetFileName」メソッド自体を調べると、
名前空間「System.IO」と書かれていましたが、こちらもコントローラの上部でImportできており、
手詰まりになってしまいました。

補足情報(FW/ツールのバージョンなど)

※エラー画像
イメージ説明

統合開発環境
Visual Studio2019
(言語:VB.NET、プロジェクトテンプレート:ASP.NET Webアプリケーション MVC)

MVCフレームワークのバージョン
5.2.7

使用PC
Windows10

※平日は仕事のため、返信が19:30以降になります。(22時以降は返信が翌日になることが多いです)
※休日の返信は不定期です。
申し訳ございませんが、どうぞよろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

ローカル変数のpathとSystem.IO 名前空間が重複してるからでは?
(「path」と書かれたら、どっちか判断できない)

System.IO.path.GetFileName(postedFile.FileName)にするか、
変数名のほうを変えるかすれば直ると思います。

どちらかというと変数名を変える方がよいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/15 19:49

    >mdj様

    >System.IO.path.GetFileName(postedFile.FileName)にするか、
    →書き換えてみて、エラーが消えました。System.IOという名前空間のもとに、GetFileNameが存在するという意識を全く持てておりませんでした。
    勉強になりました。
    ありがとうございます!

    ※後ほどいただいたアドバイスの通り、変数名を変更しました。

    キャンセル

  • この投稿は削除されました

  • 2020/07/15 21:19 編集

    hidoriさん
    はい、同一視します。
    またVisual StudioのVBでは変数宣言した時(ないしは呼び出した関数、クラス)の大文字小文字が基準になり、それ以降の関数内などの記述には自動的にそれに揃えられます。

    ※コメント先を間違えたの解釈を間違っておりました。失礼しました。

    キャンセル

0

エラーの原因は

>「Path.GetFileName」となっている箇所が、「path.GetFileName」と「p」が小文字になっていた

であってると思います。

>修正箇所からカーソルが外れると、自動的に「path」に戻りました。

という動きが不可解です。

何か、Visual Studio の機能拡張が悪さをしているとか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/16 20:24

    >hidori様

    AppendFormat("" SELECT * FROM テーブル名 ")
    みたいな書き方をしていたと思います。
    LINQは今の現場では使われていないです。。

    キャンセル

  • 2020/07/16 20:31 編集

    文字列ですね。

    ソースコード中に文字列として書かれた SQL 文が大文字であるか小文字であるかは、VB や Visual Studio ではなく、DB がどれをどう扱うか、の問題です。

    さすがに、ソースコード中に文字列として書かれた SQL 文を IDE が自動的に訂正したら大事ですね (^^;

    キャンセル

  • 2020/07/16 20:36

    じゃあSQLになるんですね。
    わかりました!ありがとうございます。

    キャンセル

0

質問のアクションメソッドのコードは、参考にしている 3 つの記事の最後の記事 MVC でファイルのアップロード のコードをコピーして、それと違うのは C# を VB.NET に変換しただけですよね?

参考にしている記事は自分が書いたもので、期待通り動くことは確認済みで、もちろんこのスレッドのような問題はありません。

と言うことは、C# と VB.NET のエディタの違いかもしれません。(VB.NET は、 Try とタイプすると Catch Exception と追加するといった「小さな親切大きなお世話」的なことが多いようです)

そのあたりを調べてみてはいかがですか?

個人的には VB.NET は止めて C# に切り替えることをお勧めしたいです。VB.NET の未来は明るくないようですし。

【追記】

今思い出したのですが、VB.NET は変数名の大文字・小文字の区別はしないのですよね。だからこういう問題 (patn と Path の区別ができない。なのでエディタが黙って Path を path に変えてしまう) が起こるのでは。

やっぱり、VB.NET を使うのは考え直した方がよさそうです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/16 14:55

    > 仕事の関係上、選択権の有無は僕にはないのですが、

    決定権のある人に先の記事を見てもらうといいですよ
    それでもなおVBのままでいいというのであればそのうち仕事がなくなるかもしれません

    キャンセル

  • 2020/07/16 15:01

    前後しますが・・・
    > 「チーム開発」で各々が好き勝手に大文字小文字の区別なく書いてしまっても、動くが故に

    まず、同じ変数やプロパティに対して各々が大文字小文字を区別せずに書いたとしても、そこはVSが自動で定義された形で調整してくれるので全く問題になりません
    今どきVSを使わずにテキストエディタで書いてるのなら別ですが

    次に、動くがゆえにとありますが、問題になる部分は大文字小文字で違いを作った別物を定義していてもコンパイラでは区別がつかない状態になると一番優先順位の高いものとして扱うことから、型が違う場合やプロパティやメソッドを使用する場合ではコンパイルエラーとなり、動く以前の問題が発生します。つまり動いていません

    キャンセル

  • 2020/07/16 20:22

    >len_suoko様

    とても詳しくありがとうございます。

    >VBだと大文字小文字の区別がないために、コードではクラスのつもりで書いたPathと変数のつもりで書いたpathがコンパイラでは同じものを書いてると判断し、そのためによりスコープ(有効範囲)の狭い変数の方を優先されて小文字に変換されるとなっているということです
    →それは怖いですね。有効範囲が広ければ良いというわけではないかもしれませんが、知らずに書いているとどんどんエラーの原因が量産されてしまいそうです。

    >VBは初心者向けの言語というはずなのに、初心者だと気づけない仕様があるというのが致命的なのでは?ということなのかなと思っています
    →皆さんがVBを止める理由がなんとなくわかってきた気がします。

    VB.NETが初心者向けの言語と言われていると思っていたのですが、今回皆さんからいただいたアドバイスと、自身が、他の言語の学習に比べて情報が少なくてすぐに詰まってしまうデメリットを総合すると、VBを主軸に置く考えは、捨てた方が良さそうですね。
    もちろん色々な言語に広く浅く手を出しても、身につかないと思うので、今は目の前のことをこなすことを第一にしますが、中長期的な計画としてはVBに重きを置きすぎないようにして考えようと思います。

    色々と教えてくださり、ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る