You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

虚拟文件存储开发求助:文件上传后的数据库存储与视图展示

解决方案:文件存储到数据库 + 文件列表展示操作

针对你遇到的两个问题,我会一步步帮你修改现有代码来解决:


一、将文件名和文件路径保存到数据库

当前你的文件上传和表单数据提交是分开执行的(文件选择后立即Ajax上传,表单提交时只保存其他字段),这会导致文件和文档元数据无法关联。我们需要调整流程,在表单提交时同时处理文件上传和数据保存,并将文件信息存入数据库。

1. 修改前端代码(合并文件与表单提交逻辑)

首先移除原来独立的文件上传Ajax,改为监听表单提交事件,用Ajax统一提交所有字段和文件:

<div class="modal-body">
@using (Html.BeginForm("SaveRecord", "NgarkoDokument", FormMethod.Post, new { enctype = "multipart/form-data", id = "documentForm" }))
{
    <!-- 原有的表单内容保持不变 -->
    <div class="row" id="ruaj">
        <button title="Ruaj dokumentin" type="submit" class="btn btn-success">Ruaj</button>
    </div>
}
</div>

<script type="text/javascript">
$(document).ready(function () {
    // 监听表单提交
    $("#documentForm").submit(function(e) {
        e.preventDefault(); // 阻止默认跳转
        var formData = new FormData(this); // 自动包含所有表单字段和文件

        $.ajax({
            type: "POST",
            url: this.action,
            data: formData,
            dataType: 'json',
            contentType: false,
            processData: false,
            success: function (response) {
                response.success 
                    ? (alert('Dokumenti u ruajt me sukses!'), $('#yourModalId').modal('hide'))
                    : alert('Gabim gjatë ruajtjes: ' + response.message);
            },
            error: () => alert('Gabim në komunikimin me serverin!')
        });
    });

    // 保持原有的文件列表展示函数
    function updateList() {
        const input = document.getElementById('file');
        const output = document.getElementById('fileList');
        output.innerHTML = '';
        for (let i = 0; i < input.files.length; ++i) {
            output.innerHTML += `<p>${input.files.item(i).name}</p>`;
        }
    }
});
</script>

2. 更新模型与Controller方法

首先确保Dokumenti实体包含文件相关字段:

public class Dokumenti
{
    public int ID { get; set; }
    public string Emer { get; set; }
    public string EmriFile { get; set; } // 存储文件名
    public string PathFile { get; set; } // 存储文件相对路径
    // 关联字段
    public int Vendndodhja_FizikeID { get; set; }
    public int Fusha_IndeksimitID { get; set; }
    public virtual Vendndodhja_Fizike Vendndodhja_Fizike { get; set; }
    public virtual Fusha_Indeksimit Fusha_Indeksimit { get; set; }
}

然后修改SaveRecord方法,统一处理文件上传和数据保存:

[HttpPost]
public JsonResult SaveRecord(NgarkoDokument model)
{
    try
    {
        // 1. 保存物理位置数据
        var vendndodhja = new Vendndodhja_Fizike
        {
            Zyra = model.Vendndodhja_fizike.Zyra,
            Rafti = model.Vendndodhja_fizike.Rafti,
            Nr_Kutise = model.Vendndodhja_fizike.Nr_Kutise
        };
        db.Vendndodhja_Fizike.Add(vendndodhja);
        db.SaveChanges();

        // 2. 保存索引字段数据
        var indeksimi = new Fusha_Indeksimit
        {
            Emri_Indeksimit = model.Fusha_Indeksimit.Emri_Indeksimit
        };
        db.Fusha_Indeksimit.Add(indeksimi);
        db.SaveChanges();

        // 3. 处理文件并保存文档记录
        for (int i = 0; i < Request.Files.Count; i++)
        {
            var file = Request.Files[i];
            if (file.ContentLength <= 0) continue;

            // 生成唯一文件名避免覆盖
            var uniqueFileName = $"{Guid.NewGuid()}_{Path.GetFileName(file.FileName)}";
            var relativePath = $"~/App_Data/File/{uniqueFileName}";
            var physicalPath = Server.MapPath(relativePath);
            
            file.SaveAs(physicalPath);

            // 保存到数据库
            var dok = new Dokumenti
            {
                Emer = model.Dokumenti.Emer,
                EmriFile = uniqueFileName,
                PathFile = relativePath,
                Vendndodhja_FizikeID = vendndodhja.ID,
                Fusha_IndeksimitID = indeksimi.ID
            };
            db.Dokumenti.Add(dok);
        }
        db.SaveChanges();

        return Json(new { success = true });
    }
    catch(Exception ex)
    {
        return Json(new { success = false, message = ex.Message });
    }
}

二、在视图中展示文件并支持操作

接下来我们在Dokument视图中展示所有文件,并添加查看、下载、删除功能。

1. 修改Dokument控制器方法,查询关联数据

public ActionResult Dokument()
{
    var dokumentet = db.Dokumenti
        .Include(d => d.Vendndodhja_Fizike)
        .Include(d => d.Fusha_Indeksimit)
        .ToList();
    return View(dokumentet);
}

2. 渲染文件列表视图(强类型视图,模型为List<Dokumenti>)

@model List<Dokumenti>

<h2>Lista e Dokumenteve</h2>

<table class="table table-striped">
    <thead>
        <tr>
            <th>Emri i Dokumentit</th>
            <th>Emri i File</th>
            <th>Zyra</th>
            <th>Kutia</th>
            <th>Rafti</th>
            <th>Indeksimi</th>
            <th>Operacione</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var dok in Model)
        {
            <tr>
                <td>@dok.Emer</td>
                <td>@dok.EmriFile</td>
                <td>@dok.Vendndodhja_Fizike.Zyra</td>
                <td>@dok.Vendndodhja_Fizike.Nr_Kutise</td>
                <td>@dok.Vendndodhja_Fizike.Rafti</td>
                <td>@dok.Fusha_Indeksimit.Emri_Indeksimit</td>
                <td>
                    <a href="@Url.Action("ViewFile", "NgarkoDokument", new { id = dok.ID })" target="_blank" class="btn btn-sm btn-primary">Shiko</a>
                    <a href="@Url.Action("DownloadFile", "NgarkoDokument", new { id = dok.ID })" class="btn btn-sm btn-success">Shkarko</a>
                    <button onclick="deleteDocument(@dok.ID)" class="btn btn-sm btn-danger">Fshi</button>
                </td>
            </tr>
        }
    </tbody>
</table>

<script type="text/javascript">
function deleteDocument(documentId) {
    if(confirm('A jeni i sigurt që doni të fshini këtë dokument?')) {
        $.ajax({
            type: "POST",
            url: '@Url.Action("DeleteDocument", "NgarkoDokument")',
            data: { id: documentId },
            success: function(response) {
                response.success 
                    ? (alert('Dokumenti u fshi me sukses!'), location.reload())
                    : alert('Gabim gjatë fshirjes: ' + response.message);
            }
        });
    }
}
</script>

3. 添加Controller操作方法(查看、下载、删除)

// 预览文件(支持浏览器可直接渲染的格式:图片、PDF、文本等)
public ActionResult ViewFile(int id)
{
    var dok = db.Dokumenti.Find(id);
    if(dok == null) return HttpNotFound();
    
    var physicalPath = Server.MapPath(dok.PathFile);
    var contentType = MimeMapping.GetMimeMapping(physicalPath);
    return File(physicalPath, contentType);
}

// 下载文件
public ActionResult DownloadFile(int id)
{
    var dok = db.Dokumenti.Find(id);
    if(dok == null) return HttpNotFound();
    
    var physicalPath = Server.MapPath(dok.PathFile);
    return File(physicalPath, MimeMapping.GetMimeMapping(physicalPath), dok.EmriFile);
}

// 删除文件与数据库记录
[HttpPost]
public JsonResult DeleteDocument(int id)
{
    try
    {
        var dok = db.Dokumenti.Find(id);
        if(dok == null) return Json(new { success = false, message = "Dokumenti nuk u gjet!" });
        
        // 删除服务器文件
        var physicalPath = Server.MapPath(dok.PathFile);
        if(System.IO.File.Exists(physicalPath))
            System.IO.File.Delete(physicalPath);
        
        // 删除数据库记录
        db.Dokumenti.Remove(dok);
        db.SaveChanges();
        
        return Json(new { success = true });
    }
    catch(Exception ex)
    {
        return Json(new { success = false, message = ex.Message });
    }
}

额外优化建议

  • 文件类型/大小限制:在Controller中添加校验,比如限制仅上传PDF/Word/图片,单个文件不超过10MB。
  • 错误提示优化:用前端弹窗组件代替alert,提升用户体验。
  • 分页功能:如果文件数量多,添加分页查询,避免页面加载过慢。

内容的提问来源于stack exchange,提问作者kris7i

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 20:47:39