2013-08-06 2 views
2

В настоящее время я разрабатываю приложение с использованием mvc 3 и C#. Мне нужно реализовать контроллер для загрузки файлов. У меня есть таблица db, в которой хранятся метаданные файла, имя, размер, тип, путь к файлу, назначение и т. Д. Я хочу сохранить фактический файл как blob на сервере azure windows и использовать строку db как указатель на нее ,Загрузка файлов как атомная операция

Я хотел бы сохранить элемент, связанный с файлом, например, профиль лица (цель), например, затем выполнить загрузку после того, как я получу первичный ключ для профиля, чтобы я мог создать необходимую ассоциацию, а затем загрузить файл и сохранить метаданные файла.

Как это сделать, если пользователь может выбрать файл до нажатия кнопки, чтобы сохранить страницу профиля.

Похоже, мне пришлось бы как-то записать файл в переменную сеанса или записать файл в какую-либо временную папку (этап), прежде чем завершить оставшиеся шаги. Есть ли лучший способ выполнить эти шаги, которые гарантировали бы атомарность?

+1

Часть загрузки файла выполняется перед сохранением человека? – Matthew

+0

Возможно, я слишком просто, но почему бы вам просто не сохранить его и не отслеживать этот идентификатор, а затем обновить дополнительные метаданные в файле, если/когда вы его получите? Есть ли процесс, который очищает без метаданных * требуемых * после X времени или асинхронизации в событии выгрузки окна? – wilso132

ответ

0

Непонятно, с какого вопроса вы столкнулись.

Если у вас есть форма html multipart/form-data, отправляемая в контроллер, файл отправляется вместе с остальными данными в виде одного запроса. Когда вы будете готовы что-то сделать с данными файла, вы просто получите доступ к свойству InpustStreamHttpPostedFileBase, который, как я полагаю, вы автоматически привязываете. Нет необходимости сохранять временный файл, IIS уже сделал это для вас.

Если, с другой стороны, вы хотите, чтобы профиль был создан до , любые данные загружаются, тогда вам придется обрабатывать их с помощью отдельных HTTP-запросов (Но это противоположность атомной операции , поэтому я предполагаю, что это не то, что вам нужно.)

Если вы хотите обработать случай, когда файл загружается успешно, но сервер обнаруживает проблемы с какой-либо другой частью формы, и вы не Не хотите, чтобы пользователь должен был снова ждать загрузки файла, да, вы захотите сохранить ссылку на файл где-то временный, чтобы он не терялся между запросами (например, переменная сеанса или запись обратно в скрытое поле в форме).

+0

Проблема, с которой я сталкиваюсь, заключается в том, как я могу гарантировать, что либо операция с базой данных, и загрузка файлов успешны, либо оба они не работают. Таким образом, база данных откатывается назад, и файл никогда не подталкивается к серверу. Оба сейфа происходят в пределах уровня обслуживания. – user1790300

+1

1. Откройте транзакцию базы данных 2. Выполните операции с базой данных (используйте для отправки метаданных ссылку на «ДобавитьFileBase») 3. Загрузить файл 4. Commit transaction 5. Если сбой до 4 транзакций отката. Если сбой в течение 4, удалите файл. –

+0

В тех случаях, перед чем-либо, я делаю минимальную вставку, получаю сгенерированный идентификатор и использую ее для ссылки на фотографию, пока процессы не завершат идентификатор, помечен как «временный». Следующий пользователь, который публикует сообщения автоматически, ищет те, срок действия которых истекает (после разумного времени), временный и удаляемый, чем и фотографии, связанные с незавершенным процессом –

1

Какую базу данных вы используете? Вы можете начать делать это атомным, обернув вашу вставку для получения первичного ключа в Try/улове, используя SQLTransaction Class, используя SqlTransaction.Rollback Method и SqlTransaction.Commit Method's, чтобы отменить вставку, если какие-либо исключения перехватываются с передачей файла

try 
{ 
// conn.BeginTransaction(); 
// Insert 
// File Transfer 
// Catch Exceptions 
// transaction.Commit(); 
} 
catch (Exception ex) 
{ 
    // Roll back Insert if file transfer fails 
    // transaction.Rollback(); 
} 
5

IMHO проблема заключается в том, что архитектор думал об этом процессе как о атомной операции, в то время как пользовательский опыт говорил бы иначе. Вы находитесь в центре конфликта. =)

Вы можете гарантировать атомарность для двух отдельных процессов и целостность данных после процесса. Позвольте мне сделать некоторые догадки, и предположим, что вы реализуете процесс создания профиля для текущего (интерактивного) пользователя.

  • Позвольте пользователю загрузить свою фотографию; скопируйте его в хранилище, отметьте его как транзакцию, добавьте к нему метаданные SessionID.

  • После того, как пользователь закончит создание своего профиля, сканируйте хранилище для изображений с тем же SessionID.Свяжите два вместе (например, ассоциируйте идентификатор файла с идентификатором профиля). Более сложный процесс будет включать, например, файл cookie с профилем, содержащий исключительный идентификатор, который должен быть сохранен вместо этого, поэтому, если пользователь покидает этот сеанс и возвращается позже загруженный файл все еще можно использовать.

  • Внесите сборщик мусора. Избавьтесь от неиспользуемых файлов после того, как порог выполняется (время или иначе.)

Я знаю, что эти предложения точно не прикрывайте первоначальный запрос, но они могут служить для оптимизации вашей реализации.

Смежные вопросы